// 防止头文件重复包含
#pragma once
#include <string>
#include <cstddef> // 提供 std::size_t 类型
#include <boost/date_time/posix_time/posix_time.hpp> // Boost 日期时间库（此处未直接使用，可能为后续扩展预留）
#include <odb/nullable.hxx> // ODB 库的可空类型，用于数据库字段允许 NULL
#include <odb/core.hxx> // ODB 核心头文件，提供对象-关系映射基础功能

// 声明 Student 为 ODB 持久化对象（对应数据库表）
#pragma db object
class Student{
public:
    // 默认构造函数（ODB 要求持久化类必须有默认构造函数）
    Student() {}
    // 带参构造函数，初始化学生学号、姓名、年龄、班级ID
    Student(unsigned long sn, const std::string &name, unsigned short age, unsigned long cid):
        _sn(sn), _name(name), _age(age), _classes_id(cid){}
    
    // 学号（_sn）的 setter 和 getter
    void sn(unsigned long num) { _sn = num; }
    unsigned long sn() { return _sn; }

    // 姓名（_name）的 setter 和 getter
    void name(const std::string &name) { _name = name; }
    std::string name() { return _name; }

    // 年龄（_age）的 setter 和 getter（返回可空类型，因为年龄可能为 NULL）
    void age(unsigned short num) { _age = num; }
    odb::nullable<unsigned short> age() { return _age; }

    // 班级ID（_classes_id）的 setter 和 getter
    void classes_id(unsigned long cid) { _classes_id = cid; }
    unsigned long classes_id() { return _classes_id; }

private:
    // 允许 ODB 访问私有成员（ODB 需要操作私有字段进行数据库映射）
    friend class odb::access;
    // 声明 _id 为数据库主键，auto 表示自增
    #pragma db id auto
    unsigned long _id;
    // 声明 _sn（学号）为唯一键（数据库中对应唯一约束）
    #pragma db unique
    unsigned long _sn;
    std::string _name; // 姓名（非空，默认映射为 NOT NULL）
    odb::nullable<unsigned short> _age; // 年龄（可空，对应数据库 NULL）
    // 为 _classes_id（班级ID）创建索引（加速关联查询）
    #pragma db index
    unsigned long _classes_id; // 关联的班级ID（外键逻辑，此处未显式声明外键约束）
};

// 声明 Classes 为 ODB 持久化对象（对应数据库表）
#pragma db object
class Classes {
public:
    // 默认构造函数（ODB 要求）
    Classes() {}
    // 带参构造函数，初始化班级名称
    Classes(const std::string &name) : _name(name){}
    
    // 班级名称（_name）的 setter 和 getter
    void name(const std::string &name) { _name = name; }
    std::string name() { return _name; }

private:
    friend class odb::access; // 允许 ODB 访问私有成员
    #pragma db id auto // 声明 _id 为自增主键
    unsigned long _id;
    std::string _name; // 班级名称
};

// ODB 视图：关联查询学生信息和对应班级名称
// 关联 Student 和 Classes 表 关联条件：Student._classes_id == Classes._id（通过别名 classes 引用 Classes）
#pragma db view object(Student)\
                object(Classes = classes : Student::_classes_id == classes::_id)\
                query((?)) // 允许外部传入查询条件（占位符）
struct classes_student {
    #pragma db column(Student::_id) // 映射 Student 表的 _id 字段
    unsigned long id;
    #pragma db column(Student::_sn) // 映射 Student 表的 _sn 字段
    unsigned long sn;
    #pragma db column(Student::_name) // 映射 Student 表的 _name 字段
    std::string name;
    #pragma db column(Student::_age) // 映射 Student 表的 _age 字段
    odb::nullable<unsigned short>age;
    #pragma db column(classes::_name) // 映射 Classes 表（别名 classes）的 _name 字段（班级名称）
    std::string classes_name;
};

// ODB 视图：仅查询学生姓名，支持外部传入过滤条件
// 自定义 SQL 模板："select name from Student" 后拼接外部条件（如 "where age > 18"）
#pragma db view query("select name from Student")
struct all_name {
    std::string name; // 映射查询结果中的 name 字段
};

//odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time student.hxx